package com.ai.networking.netty.client;


import com.ai.entity.comm.SysNetty;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import lombok.extern.slf4j.Slf4j;

/**
 * netty 客户端
 * 蚂蚁舞
 */
@Slf4j
public class BootNettyClient {

    public void connect(SysNetty sysNetty) throws Exception {

        /**
         * 客户端的NIO线程组
         */
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            /**
             * Bootstrap 是一个启动NIO服务的辅助启动类 客户端的
             */
            Bootstrap bootstrap = new Bootstrap();
            bootstrap = bootstrap.group(group);
            if (sysNetty.getRegularPort() != 0) {
                bootstrap.localAddress("", sysNetty.getRegularPort());
            }

            bootstrap = bootstrap.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true);
            /**
             * 设置 I/O处理类,主要用于网络I/O事件，记录日志，编码、解码消息
             */
            bootstrap = bootstrap.handler(new BootNettyChannelInitializer<SocketChannel>(sysNetty));
            /**
             * 连接服务端
             *  连接失败不进行重连操作或者其他操作恶魔
             */
            ChannelFuture future = bootstrap.connect(sysNetty.getIp(), sysNetty.getPort()).sync();
            if (future.isSuccess()) {
                Channel channel = future.channel();
                BootNettyClientChannel bootNettyClientChannel = new BootNettyClientChannel();
                bootNettyClientChannel.setChannel(channel);
                bootNettyClientChannel.setCode("clientCode:" + sysNetty.getCode());

                //连接建立之后，将channel保存到内存中
                BootNettyClientChannelCache.save(sysNetty.getCode(), bootNettyClientChannel);
                log.info("netty client start success=" + sysNetty.getCode());
                /**
                 * 等待连接端口关闭
                 */
                future.channel().closeFuture().sync();
            }
        } finally {
            /**
             * 退出，释放资源
             */
            group.shutdownGracefully().sync();
            log.info("退出，释放资源");
        }
    }
}